import Chromosome from './Chromosome.js';
import evaluateSOO from './evaluateSOO.js';
// import rand from './rand.js';
import crossover from './crossover.js';
import mutate from './mutate.js';
function SOO(
  matrix,
  edgeData,
  pop,
  gen,
  selectionProcess,
  mutateProbability,
  useLocalSearch,
  useLocalSearchProbability,
  targetFunction = 'H',
  w
) {
  if (pop % 2 !== 0) pop = pop + 1;
  const result = new Array(gen);
  let bestValue = {};
  let population = new Array(pop);
  const maxNodeNum = matrix.length;
  const matrixNum = 1;
  // 初始化
  for (let i = 0; i < pop; i++) {
    population[i] = new Chromosome(matrixNum, maxNodeNum);
    population[i].initialize(matrix);
  }
  // 评估，计算目标函数值
  for (let i = 0; i < pop; i++) {
    evaluateSOO(
      matrix,
      edgeData,
      population[i],
      false,
      useLocalSearchProbability,
      targetFunction,
      undefined,
      w
    );
  }
  // 找出最大的目标值
  bestValue.target = population[0].factorialCosts[0];
  bestValue.rnvec = population[0].rnvec;
  for (let i = 1; i < pop; i++) {
    if (population[i].factorialCosts[0] > bestValue.target) {
      bestValue.target = population[i].factorialCosts[0];
      bestValue.rnvec = population[i].rnvec;
    }
  }
  result[0] = { ...bestValue };
  // 迭代交叉变异
  for (let g = 1; g < gen; g++) {
    const childs = [];
    // 打乱顺序
    population.sort((a, b) => Math.random() - 0.5);
    for (let i = 0; i < pop / 2; i++) {
      let index1 = i;
      let index2 = i + pop / 2;
      let child1 = new Chromosome(matrixNum, maxNodeNum);
      let child2 = new Chromosome(matrixNum, maxNodeNum);
      child1.rnvec = crossover(population[index1].rnvec, population[index2].rnvec);
      child2.rnvec = crossover(population[index2].rnvec, population[index1].rnvec);
      if (Math.random() < mutateProbability) {
        mutate(child1.rnvec, matrix);
      }
      if (Math.random() < mutateProbability) {
        mutate(child2.rnvec, matrix);
      }
      childs.push(child1);
      childs.push(child2);
    }
    // 评估，计算目标函数值
    for (let i = 0; i < pop; i++) {
      evaluateSOO(
        matrix,
        edgeData,
        childs[i],
        useLocalSearch,
        useLocalSearchProbability,
        targetFunction,
        bestValue,
        w
      );
    }
    // 合并子代和父代
    let parentsAndChilds = [...population, ...childs];
    // 找出最大的目标值
    for (let i = 1; i < pop * 2; i++) {
      if (parentsAndChilds[i].factorialCosts[0] > bestValue.target) {
        bestValue.target = parentsAndChilds[i].factorialCosts[0];
        bestValue.rnvec = parentsAndChilds[i].rnvec;
      }
    }
    result[g] = { ...bestValue };
    // 选择算子
    if (selectionProcess === 'elitist') {
      parentsAndChilds.sort((a, b) => b.factorialCosts[0] - a.factorialCosts[0]);
      population = parentsAndChilds.slice(0, pop);
    }
    // console.log(bestValue.target);
  }
  return result;
}
export default SOO;
